package io.openkunlun.javadsl.serialization;

import com.fasterxml.jackson.databind.JavaType;
import com.google.protobuf.ByteString;
import io.openkunlun.javadsl.v1.DaprSerializationProtos;

import java.io.IOException;

public class JacksonDelegatingSerializer extends DelegatingSerializer {

    private final JacksonSerializer delegate;

    public JacksonDelegatingSerializer(JacksonSerializer delegate) {
        this.delegate = delegate;
    }

    @Override
    final protected DaprSerializationProtos.SerializationManifest serializeWithManifest(Object o) throws IOException {
        // [B
        byte[] payload = delegate.serialize(o);
        JavaType javaType = null != o ? delegate.getMapper().constructType(o.getClass()) : null;
        return DaprSerializationProtos.SerializationManifest
                .newBuilder()
                .setManifest(null != javaType ? javaType.toCanonical(): "")
                .setPayload(ByteString.copyFrom(payload))
                .setIsStringManifest(false)
                .setSerializerId(-1)
                .build();
    }

    @Override
    final protected <T> DaprSerializationProtos.SerializationManifest serializeWithManifest(Object o, DaprObject<T> type) throws IOException {
        byte[] payload = delegate.serialize(o, type);
        JavaType javaType = delegate.getMapper().constructType(type.getType());
        return DaprSerializationProtos.SerializationManifest
                .newBuilder()
                .setManifest(javaType.toCanonical())
                .setPayload(ByteString.copyFrom(payload))
                .setIsStringManifest(false)
                .setSerializerId(-1)
                .build();
    }

    @Override
    final protected <T> T deserializeWithManifest(DaprSerializationProtos.SerializationManifest manifest, Class<T> type) throws IOException {
        String stringManifest = manifest.getManifest();
        if (stringManifest.isEmpty()) {
            return delegate.deserialize(manifest.getPayload().toByteArray(), type);
        }

        JavaType javaType = delegate.getMapper().getTypeFactory().constructFromCanonical(stringManifest);
        return delegate.deserialize(manifest.getPayload().toByteArray(), javaType);
    }

    @Override
    final protected <T> T deserializeWithManifest(DaprSerializationProtos.SerializationManifest manifest, DaprObject<T> type) throws IOException {
        String stringManifest = manifest.getManifest();
        if (stringManifest.isEmpty()) {
            return delegate.deserialize(manifest.getPayload().toByteArray(), type);
        }

        JavaType javaType = delegate.getMapper().getTypeFactory().constructFromCanonical(stringManifest);
        return delegate.deserialize(manifest.getPayload().toByteArray(), javaType);
    }
}
